package ru.sgu.diploma.practic.gui.dftab;

import org.springframework.beans.factory.annotation.Autowired;
import ru.sgu.diploma.practic.domain.model.*;
import ru.sgu.diploma.practic.errors.NextLetterException;
import ru.sgu.diploma.practic.errors.TranslateException;
import ru.sgu.diploma.practic.gui.MainWindow;
import ru.sgu.diploma.practic.service.*;
import ru.sgu.diploma.practic.utils.GeometricModelUtils;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * User: datmakin
 * Date: 16.03.11
 * Email: atmakin.dv@gmail.com
 */
public class DetermineFuntionTab extends JPanel {
    private JLabel counterLabel = new JLabel("обработано входных значений: ");
    private JLabel counter = new JLabel("0");
    private JButton start = new JButton("запустить");
    private JPanel imagePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    private boolean stop = false;

    private BufferedImage bufferedImage = null;
    Thread processor = new Thread(new StartButtonProcessor());
    @Autowired
    MainWindow mainWindow;

    @Autowired
    StatesGenerator statesGenerator;

    @Autowired
    AutomatGenerator automatGenerator;

    @Autowired
    AutomatUltraMetricResultConverter automatUltraMetricResultConverter;

    @Autowired
    ImageConstructor imageConstructor;

    @Autowired
    private TranslateFunction determineFunctionTranslater;

    public void prepare() {

        this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

        imagePanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("геометрический образ"),
                BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!stop) {
                    processor = new Thread(new StartButtonProcessor());
                    processor.start();
                    stop = true;
                    start.setText("остановить");
                } else {
                    processor.stop();
                    stop = false;
                    start.setText("запустить");
                }
            }
        });

        this.add(imagePanel);
        Box box = Box.createHorizontalBox();

        JButton save = new JButton("сохранить");
        save.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                File outputfile = new File("sample1.png");
                try {
                    ImageIO.write(bufferedImage, "png", outputfile);
                } catch (IOException ex) {
                    System.out.print("fatal error while saving result: " + ex.getMessage());
                    System.exit(0);
                }
            }
        });
        box.add(save);
        box.add(Box.createHorizontalGlue());
        box.add(counterLabel);
        box.add(counter);
        box.add(Box.createHorizontalGlue());
        box.add(start);
        this.add(box);

    }

    private void processCounter(Integer a) {
        counter.setText(a.toString());
    }

    class StartButtonProcessor implements Runnable {
        public void run() {
            java.util.List<ru.sgu.diploma.practic.domain.model.Point> pointList = new LinkedList<ru.sgu.diploma.practic.domain.model.Point>();
            for (int a = 0; a < 100000; a++) {
                Thread.yield();
                String[] input = statesGenerator.generateStateForAlphabet(determineFunctionTranslater.getAlphabet());
                String[] output = null;
                try {
                    output = determineFunctionTranslater.translate(input);
                } catch (TranslateException e) {
                    //
                }

                java.util.List<ru.sgu.diploma.practic.domain.model.Point> prPoint = null;
                try {
                    prPoint = automatUltraMetricResultConverter.convert(input, output, determineFunctionTranslater.getAlphabet());
                } catch (NextLetterException e) {
                    //
                }
                pointList.addAll(prPoint);

                if (a % 1000 == 0) {
                    processCounter(a);
                    GeometricModel geometricModel = new GeometricModel();
                    geometricModel.setPointList(pointList);
                    geometricModel.setImageResolution(GeometricModelUtils.calculateResolution(geometricModel));
                    BufferedImage bi = imageConstructor.constructWithScale(geometricModel, 1);
                    bufferedImage = GeometricModelUtils.verticalflip(bi);
                    Image image = new Image(bufferedImage);
                    imagePanel.removeAll();
                    imagePanel.add(image);


                }
            }

            GeometricModel geometricModel = new GeometricModel();
            geometricModel.setPointList(pointList);
            geometricModel.setImageResolution(GeometricModelUtils.calculateResolution(geometricModel));
            BufferedImage bi = imageConstructor.constructWithScale(geometricModel, 1);
            bufferedImage = GeometricModelUtils.verticalflip(bi);
            Image image = new Image(bufferedImage);
            imagePanel.removeAll();
            imagePanel.add(image);


        }

    }

    public JButton getStart() {
        return start;
    }

    public void setStart(JButton start) {
        this.start = start;
    }

    public JPanel getImagePanel() {
        return imagePanel;
    }

    public void setImagePanel(JPanel imagePanel) {
        this.imagePanel = imagePanel;
    }

    public StatesGenerator getStatesGenerator() {
        return statesGenerator;
    }

    public void setStatesGenerator(StatesGenerator statesGenerator) {
        this.statesGenerator = statesGenerator;
    }

    public AutomatGenerator getAutomatGenerator() {
        return automatGenerator;
    }

    public void setAutomatGenerator(AutomatGenerator automatGenerator) {
        this.automatGenerator = automatGenerator;
    }

    public AutomatUltraMetricResultConverter getAutomatUltraMetricResultConverter() {
        return automatUltraMetricResultConverter;
    }

    public void setAutomatUltraMetricResultConverter(AutomatUltraMetricResultConverter automatUltraMetricResultConverter) {
        this.automatUltraMetricResultConverter = automatUltraMetricResultConverter;
    }

    public ImageConstructor getImageConstructor() {
        return imageConstructor;
    }

    public void setImageConstructor(ImageConstructor imageConstructor) {
        this.imageConstructor = imageConstructor;
    }

    public TranslateFunction getDetermineFunctionTranslater() {
        return determineFunctionTranslater;
    }

    public void setDetermineFunctionTranslater(TranslateFunction determineFunctionTranslater) {
        this.determineFunctionTranslater = determineFunctionTranslater;
    }

    public MainWindow getMainWindow() {
        return mainWindow;
    }

    public void setMainWindow(MainWindow mainWindow) {
        this.mainWindow = mainWindow;
    }
}
